import datetime
import socket
import threading

from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QMdiSubWindow
import qtawesome as qta
from pygments import highlight
from pygments.formatters.html import HtmlFormatter
from pygments.lexers.python import PythonLexer
# from pygments.lexers.python import PythonLexer
from pyqtgraph.examples.syntax import PythonHighlighter
# from pyqtgraph.examples.ExampleApp import PythonHighlighter
# from PyQt5 import uic
from qtpy import uic

from monitor import Monitor
from win_client import WinClient
from share import SI, mySignals
# from win_codehelper import WinClient
from win_loadtest import WinLoadTest


# 动态载入
class WinMain(QMainWindow):
    def __init__(self):
        super().__init__()
        # PyQt5
        self.ui = uic.loadUi("ui/main.ui")
        # 如果使用 self.show(),会产生一个空白的 MainWindow

        # 客户端ei.file
        self.ui.buttonClient.setIcon(qta.icon('fa5.user', color='#1d649c'))
        self.ui.buttonClient.setIconSize(QSize(30, 30))
        # fa.users
        # 性能场景
        self.ui.buttonConditions.setIcon(qta.icon('fa.users', color='#1d649c'))
        self.ui.buttonConditions.setIconSize(QSize(30, 30))
        # 监控统计
        self.ui.buttonMonitor.setIcon(qta.icon('fa5s.tachometer-alt', color='#1d649c'))
        self.ui.buttonMonitor.setIconSize(QSize(30, 30))
        # 远程控制
        self.ui.buttonRemoteControl.setIcon(qta.icon('mdi6.remote-desktop', color='#1d649c'))
        self.ui.buttonRemoteControl.setIconSize(QSize(30, 30))
        # 关于
        self.ui.buttonAbout.setIcon(qta.icon('mdi6.help-circle-outline', color='#1d649c'))
        self.ui.buttonAbout.setIconSize(QSize(30, 30))

        self.ui.buttonClient.clicked.connect(lambda: self.ShowMdiSubWin(WinClient))
        self.ui.buttonConditions.clicked.connect(lambda: self.ShowMdiSubWin(WinLoadTest))
        self.ui.buttonMonitor.clicked.connect(lambda: self.ShowMdiSubWin(Monitor))
        # self.ui.buttonRemoteControl.clicked.connect(lambda: self.ShowMdiSubWin(WinLoadTestMain))
        # self.ui.buttonAbout.clicked.connect(lambda: self.ShowMdiSubWin(WinLoadTestMain))

        self.ui.textBrowserLog.document().setMaximumBlockCount(1000)


        self.ui.actionOpenPath.triggered.connect(self.OpenPath)

        # 保存子窗口 的字典
        self.subWinTable = {}
        SI.LogInfo = self.LogInfo
        self.ui.show()
        # 统计信息接收和处理
        mySignals.statsRecved.connect(self.LogInfo)
        self.StatsRecvThread()

    def StatsRecvThread(self):
        # 创建统计信息接收 UDP socket
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        for i in range(200):
            try:
                self.server_socket.bind(('', SI.ListenPort))
                break
            except:
                self.LogInfo(f'绑定端口 {SI.ListenPort} 失败')
                SI.ListenPort += 1
        else:
            self.LogInfo('未能找到合适的端口')
            return

        self.LogInfo(f'绑定端口 {SI.ListenPort} 成功')
        self.ui.statusbar.showMessage(f'绑定端口 {SI.ListenPort}')



        # 启动新线程，接收 压测进程的 实时统计信息
        self.statsRecvThread = threading.Thread(
            target=self.statsRecvThreadFunc,
            daemon=True)
        self.statsRecvThread.start()
    def statsRecvThreadFunc(self):
            while True:
                try:
                    recvbytes, client_addr = self.server_socket.recvfrom(400)
                    recvStr = recvbytes.decode()
                    mySignals.statsRecved.emit(recvStr)
                except socket.timeout:
                    continue

    def OpenPath(self):
        filePath = QFileDialog.getExistingDirectory(self.ui, "选择项目路径", "./work")

        if not filePath:
            SI.WorkFilePath  = ""
            self.ui.setWindowTitle(f"小二测试工具 - 项目路径未设置")
            return
        SI.WorkFilePath = filePath
        self.ui.setWindowTitle(f"小二测试工具 - {SI.WorkFilePath}")
        self.LogInfo(f'已经选择了项目路径: {SI.WorkFilePath}')


    def ShowMdiSubWin(self, funcClass):
        if not SI.WorkFilePath:
            self.LogInfo('请先设置项目目录')
            return

        def createWin():
            subWinFunc = funcClass()
            subWindow = QMdiSubWindow()
            subWindow.setWidget(subWinFunc.ui)
            subWindow.setAttribute(Qt.WA_DeleteOnClose)
            self.ui.mdiArea.addSubWindow(subWindow)
            # subWindow.setContentsMargins(0, 0, 0, 0)
            subWindow.setWindowState(Qt.WindowActive | Qt.WindowMaximized)
            self.subWinTable[str(funcClass)] = {'subWin': subWindow, 'subWinFunc': subWinFunc}
            subWindow.show()


        if str(funcClass) not in self.subWinTable:
            # 如果子窗口尚未创建，创建并保存到字典中
            createWin()
            return

        subWindow = self.subWinTable[str(funcClass)]['subWin']
        try:
            subWindow.setWindowState(Qt.WindowActive | Qt.WindowMaximized)
            subWindow.show()
        except:
            createWin()

    def LogInfo(self, info):
        strTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]

        formatter = HtmlFormatter(style='stata-light', noclasses=True)
        highlighted_code = highlight(strTime + ': ' + info, PythonLexer(), formatter)

        # Set the highlighted code as HTML in QTextBrowser
        self.ui.textBrowserLog.append(highlighted_code)

        # self.ui.textBrowserLog.append(strTime + ': ' + info)
        self.ui.textBrowserLog.verticalScrollBar() #设置日志始终滚动最新的

